import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { RegisteByEmailDto } from './dto/registerByEmail.dto'
import { sendcodeByEmail } from './dto/sendcodeByEmail.dto'
import { Repository, Connection, getRepository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { UsersEntity } from './user.entity'
import { MailerService } from '@nest-modules/mailer';
import { RedisService } from 'nestjs-redis';
import { getRandomNum, getUuid, mailRag } from '../../common/util'
import { JwtService } from '@nestjs/jwt';
import { LoginByPasswordDto } from './dto/loginByPassword.dto'
import { LoginByCodeDto } from './dto/loginByCode.dto'
import { LoginOrRegisterSuccess, userInfo } from './classes/user'
import { ForgetPasswordSendCodeDto } from './dto/forgetPasswordSendCode.dto';
@Injectable()
export class UserService {
    public redisClient;
    constructor(
        @InjectRepository(UsersEntity)
        private readonly usersRepository: Repository<UsersEntity>,
        private redisService: RedisService,
        private readonly mailerService: MailerService,
        private readonly jwtService: JwtService,
    ) {
        this.getClient();
    }
    async getClient() {
        this.redisClient = await this.redisService.getClient()
    }
    async loginByPassword(user: LoginByPasswordDto) {
        let data: UsersEntity;
        try {
            let rs: UsersEntity;
            if (mailRag.test(user.loginUsername)) {
                rs = await this.usersRepository.findOne({ email: user.loginUsername })
            } else {
                rs = await this.usersRepository.findOne({ username: user.loginUsername })
            }
            data = rs;
            if (rs.password != user.password) {
                throw new HttpException(
                    {
                        message: '请重新确认用户名邮箱或密码是否正确。',
                        error: '用户名邮箱或密码错误。',
                    },
                    HttpStatus.BAD_REQUEST,
                );
            }
        } catch {
            throw new HttpException(
                {
                    message: '请重新确认用户名邮箱是否正确。',
                    error: '用户名邮箱或密码错误。',
                },
                HttpStatus.BAD_REQUEST,
            );
        }
        let loginOrRegisterSuccess = new LoginOrRegisterSuccess
        const payload = { username: data.username, uuid: data.uuid };
        loginOrRegisterSuccess.access_token = this.jwtService.sign(payload)
        return {
            code: 200,
            msg: "登录成功。",
            data: loginOrRegisterSuccess
        }
    }
    async loginByCode(user: LoginByCodeDto) {
        let data: UsersEntity;
        try {
            let rs = await this.usersRepository.findOne({ email: user.email })
            data = rs;
        } catch {
            throw new HttpException(
                {
                    message: '请检查用户名或邮箱。',
                    error: '用户名或邮箱未注册。',
                },
                HttpStatus.BAD_REQUEST,
            );
        }
        try {
            let Code = await this.redisClient.get(user.email)
            if (Code != user.code) {
                throw new HttpException(
                    {
                        message: '请重新检查或重新获取。',
                        error: '验证码错误或已超时。',
                    },
                    HttpStatus.BAD_REQUEST,
                );
            }
        } catch {
            throw new HttpException(
                {
                    message: '请重新检查或重新获取。',
                    error: 'redis查询失败',
                },
                HttpStatus.BAD_REQUEST,
            );
        }
        let loginOrRegisterSuccess = new LoginOrRegisterSuccess;
        const payload = { username: data.username, uuid: data.uuid };
        loginOrRegisterSuccess.access_token = this.jwtService.sign(payload)
        return {
            code: 200,
            msg: "注册成功。",
            data: loginOrRegisterSuccess
        }
    }
    async loginSendCode(Email: sendcodeByEmail) {
        let { email } = Email;
        let code = getRandomNum(1000, 9999);
        try {
            let rs = await this.usersRepository.findOne({ email });

            this.mailerService.sendMail({
                to: email,
                from: "1987852769@qq.com",
                subject: 'Zipper Love You ✔',
                template: 'login',
                context: {
                    code
                }
            }).then(() => {
                this.redisClient.set(email, code);
                this.redisClient.expire(email, 300);
            }).catch(e => {
                throw new HttpException(
                    {
                        message: '请重新获取。',
                        error: '发送邮件失败',
                    },
                    HttpStatus.BAD_REQUEST,
                );
            });
        } catch {
            throw new HttpException(
                {
                    message: '请重试。',
                    error: '邮箱查询失败。',
                },
                HttpStatus.BAD_REQUEST,
            );
        }
        return {
            code: 200,
            msg: "发送成功"
        }
    }
    async registerByEmail(registeByEmailDto: RegisteByEmailDto) {
        let { email, username, password, code } = registeByEmailDto;
        try {
            let rs1 = await this.usersRepository.findOne({ email })
            let rs2 = await this.usersRepository.findOne({ username })
        } catch {
            throw new HttpException(
                {
                    message: '请更换用户名或邮箱。',
                    error: '用户名或邮箱已注册。',
                },
                HttpStatus.BAD_REQUEST,
            );
        }

        try {
            let Code = await this.redisClient.get(email);
            if (Code != code) {
                throw new HttpException(
                    {
                        message: '请重新检查或重新获取。',
                        error: '验证码错误或已超时。',
                    },
                    HttpStatus.BAD_REQUEST,
                );
            }
        } catch {
            throw new HttpException(
                {
                    message: '请重新检查或重新获取。',
                    error: 'redis查询失败',
                },
                HttpStatus.BAD_REQUEST,
            );
        }
        let user = new UsersEntity
        user.username = username;
        user.email = email;
        user.password = password;
        user.uuid = getUuid();
        user.gmtCreate = (new Date()).valueOf().toString();
        user.gmtModified = (new Date()).valueOf().toString();
        this.usersRepository.save(user);
        let loginOrRegisterSuccess = new LoginOrRegisterSuccess;
        const payload = { username: user.username, uuid: user.uuid };
        loginOrRegisterSuccess.access_token = this.jwtService.sign(payload)
        return {
            code: 200,
            msg: "注册成功。",
            data: loginOrRegisterSuccess
        }
    }
    async registerSendcodeByEmail(Email: sendcodeByEmail) {
        let { email } = Email;
        let code = getRandomNum(1000, 9999);
        try {
            let rs = await this.usersRepository.findOne({ email });
            if (rs) {
                throw new HttpException(
                    {
                        message: '请更换邮箱。',
                        error: '邮箱已注册。',
                    },
                    HttpStatus.BAD_REQUEST,
                );
            }
        } catch {
            throw new HttpException(
                {
                    message: '请重试。',
                    error: '邮箱查询失败。',
                },
                HttpStatus.BAD_REQUEST,
            );
        }

        this.mailerService.sendMail({
            to: email,
            from: "1987852769@qq.com",
            subject: 'Zipper Love You ✔',
            template: 'register',
            context: {
                code
            }
        }).then(() => {
            this.redisClient.set(email, code);
            this.redisClient.expire(email, 300);
        }).catch(e => {
            throw new HttpException(
                {
                    message: '请重新获取。',
                    error: '发送邮件失败',
                },
                HttpStatus.BAD_REQUEST,
            );
        });
        return {
            code: 200,
            msg: "发送成功"
        }

    }
    async getUserInfo(user: { username: string; uuid: string; }) {
        let data: UsersEntity;
        try {
            let rs1 = await this.usersRepository.findOne({ username: user.username, uuid: user.uuid })
            data = rs1;
        } catch {
            throw new HttpException(
                {
                    message: '请重新登陆。',
                    error: '获取失败。',
                },
                HttpStatus.BAD_REQUEST,
            );
        }
        return {
            code: 200,
            msg: "获取成功。",
            data
        }
    }
    async forgetPasswordSendCode({ email }: ForgetPasswordSendCodeDto) {
        let data: UsersEntity;
        let code = getRandomNum(1000, 9999);
        try {
            let rs = await this.usersRepository.findOne({ email })
            data = rs;
            this.mailerService.sendMail({
                to: email,
                from: "1987852769@qq.com",
                subject: 'Zipper Love You ✔',
                template: 'login',
                context: {
                    code
                }
            }).then(() => {
                this.redisClient.set(email, code);
                this.redisClient.expire(email, 300);
            }).catch(e => {
                throw new HttpException(
                    {
                        message: '请重新获取。',
                        error: '发送邮件失败',
                    },
                    HttpStatus.BAD_REQUEST,
                );
            });
        } catch {
            throw new HttpException(
                {
                    message: '请更换用户名或邮箱。',
                    error: '用户名或邮箱未注册。',
                },
                HttpStatus.BAD_REQUEST,
            );
        }
        return
    }
}
